from abc import ABC, abstractmethod
from typing import ClassVar, Dict, Type, List

from implement.crypto.AESCryptoProcessor import AESCryptoProcessor
from interface.crypto_interfaces import CryptoProcessor


class CryptToolFactory(ABC):
    """加密工具工厂抽象基类"""

    @abstractmethod
    def create_crypt(self, password: str) -> CryptoProcessor:
        """创建加密处理器实例"""
        pass

    @classmethod
    @abstractmethod
    def is_available(cls, name: str) -> bool:
        """检查工具是否可用"""
        pass


class CryptToolFactoryRegistry:
    """工厂注册中心（单例模式）"""
    _instance: ClassVar = None
    _factories: Dict[str, Type[CryptToolFactory]] = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._initialize_default_factories()
        return cls._instance

    @classmethod
    def _initialize_default_factories(cls):
        """初始化默认工厂"""
        cls.register_factory('AESCrypto', CryptFactory)

    @classmethod
    def register_factory(cls, name: str, factory: Type[CryptToolFactory]):
        """注册新的工厂类型"""
        if not issubclass(factory, CryptToolFactory):
            raise TypeError("Factory must be a subclass of CryptToolFactory")
        cls._factories[name.lower()] = factory

    @classmethod
    def unregister_factory(cls, name: str):
        """取消注册工厂类型"""
        cls._factories.pop(name.lower(), None)

    @classmethod
    def get_factory_class(cls, name: str) -> Type[CryptToolFactory]:
        """根据名称获取工厂类"""
        return cls._factories.get(name.lower())

    @classmethod
    def get_available_factories(cls) -> List[Type[CryptToolFactory]]:
        """获取所有已注册的工厂类型"""
        return list(cls._factories.values())


class CryptFactory(CryptToolFactory):
    @classmethod
    def is_available(cls, name: str) -> bool:
        return name.lower() == "aescrypto"

    def create_crypt(self, password: str) -> CryptoProcessor:
        return AESCryptoProcessor(password)


class CryptToolFactorySelector:
    """工厂选择器"""

    @classmethod
    def select_factory(cls, name: str) -> CryptToolFactory:
        registry = CryptToolFactoryRegistry()
        factory_class = registry.get_factory_class(name)
        if factory_class and factory_class.is_available(name):
            return factory_class()
        raise ValueError(f"No available factory found for: {name}")


class JudgementCrypt:
    """加密工具选择器"""

    def __init__(self, name: str):
        self._factory = CryptToolFactorySelector.select_factory(name)

    def get_crypt_processor(self, password: str) -> CryptoProcessor:
        """获取加密处理器实例"""
        return self._factory.create_crypt(password)

    def __str__(self):
        return f"{self.__class__.__name__} [Using: {type(self._factory).__name__}]"


if __name__ == '__main__':
    crypt = JudgementCrypt("aescrypto")
    aes = crypt.get_crypt_processor(password="123456")
    print(aes)
